home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / utility / secdrv.zip / SECTSR.ASM < prev    next >
Assembly Source File  |  1993-11-19  |  28KB  |  1,110 lines

  1. ; TSR disk encryptor V1.0  
  2.  
  3. DISKDATA STRUC 
  4. FIRSTCYL  DW ?     ;FIRST CYLINDER TO ENCRYPT
  5. FIRSTHD   DB ?     ;FIRST HEAD TO ENCRYPT
  6. FIRSTSEC  DB ?     ;FIRST SECTOR (BOOT SECTOR)
  7. LASTCYL   DW ?     ;LAST CYLINDER TO ENCRYPT
  8. MAXSEC    DB ?     ;NUMBER OF SECTORS ON DEVICE
  9. MAXHD     DB ?     ;NUMBER OF HEADS ON DEVICE
  10. SECSIZE   DW ?     ;BLOCK SIZE IN BYTES
  11. SERIAL    DW ?     ;DISK SERIAL NUMBER, FOR IV
  12.           DW ?     ;REST OF DISK SERIAL NUMBER
  13. ACTIVE    DB ?     ;CRYPT THIS DISK? FLAG
  14. DISKDATA ENDS
  15.  
  16.  .MODEL TINY
  17.  .CODE
  18.  ORG 0100h
  19. START: 
  20.  MOV AX,0800h 
  21.  MOV DL,0F0h
  22.  INT 13h
  23.  CMP AX,0EDCBh ;IS IT ALREADY INSTALLED?
  24.  JNE LOADTSR
  25.  MOV AH,9
  26.  MOV DX,OFFSET ALRINS
  27.  INT 21h ;PRINT ERROR AND EXIT
  28.  INT 20h
  29. LOADTSR:
  30.  MOV AH,9
  31.  MOV DX,OFFSET FKEY
  32.  INT 21h ;PRINT SIGN-ON
  33.  
  34.  MOV AX,3513h
  35.  INT 21h ;GET INT VECTOR
  36.  MOV WORD PTR[INT_JOUT+1],BX
  37.  MOV WORD PTR[INT_JOUT+3],ES
  38.  
  39.  MOV DX,OFFSET(I13_ENTRY)
  40.  MOV AX,2513h
  41.  INT 21h ;SET NEW INT VECTOR
  42.  
  43.  MOV AX,3100h
  44.  MOV DX,(END_OF_FILE-START)/16+17
  45.  INT 21h ;GO TSR
  46. TSRSTACK: ;OUR STACK GOES HERE
  47.  NOP
  48.  
  49. I13_ENTRY:
  50.  CLI
  51.  MOV WORD PTR CS:STKSEG,SS
  52.  MOV WORD PTR CS:STKOFS,SP
  53.  MOV WORD PTR CS:IV,CS
  54.  MOV SS,WORD PTR CS:IV
  55.  MOV SP,OFFSET TSRSTACK ;SETUP OUR STACK
  56.  STI
  57.  PUSH AX
  58.  PUSH BX
  59.  PUSH CX
  60.  PUSH DX
  61.  PUSH SI
  62.  PUSH DI
  63.  PUSH BP
  64.  PUSH DS
  65.  PUSH ES
  66.  PUSH CS
  67.  POP DS
  68.  
  69. ;DECIDE IF THIS REQUEST NEEDS PROCESSING
  70.  CMP AH,2 ;READ SECTOR
  71.  JE RDORWR
  72.  CMP AH,3 ;WRITE SECTOR
  73.  JE RDORWR
  74.  CMP AH,8 ;REQUEST FOR ADDRESS?
  75.  JNE TONOPROC
  76.  CMP DL,0F0h ;CORRECT DRIVE NUMBER?
  77.  JNE TONOPROC
  78.  MOV BP,SP
  79.  MOV [BP+10],OFFSET LOADDATA ;DX=DATA ADDRESS
  80.  MOV [BP+12],CS ;CX=CODE SEGMENT
  81.  MOV AX,0EDCBh; ;THIS MEANS IT'S INSTALLED
  82.  JMP RETPROG
  83.  
  84. TONOPROC: 
  85.  JMP NOPROC
  86. RDORWR: 
  87.  MOV BYTE PTR RQTYPE,AH ;STORE REQUEST TYPE
  88.  MOV BYTE PTR NUMSEC,AL ;STORE NUMBER OF SECTORS
  89.  MOV BYTE PTR STSEC,CL  ;STORE SECTOR; MUST BE MASKED
  90.  AND BYTE PTR STSEC,00111111b ;MASK OFF HIGH 2 BITS
  91.  MOV WORD PTR CALLCX,CX ;KEEP CX FOR DISK ACCESS
  92.  MOV AH,CL              ;WE NEED TO...
  93.  MOV AL,CH              ;SWAP THESE
  94.  MOV CL,6               ;ROTATE 6 BITS...
  95.  SHR AH,CL              ;TO THE RIGHT, NOW AX CONTAINS CYLINDER
  96.  MOV BYTE PTR DRIVE,DL  ;STORE DRIVE
  97.  MOV WORD PTR STCYL,AX  ;STORE CYLINDER
  98.  MOV BYTE PTR STHD,DH   ;STORE HEAD
  99.  MOV WORD PTR BUFOS,BX  ;STORE BUFFER ADDRESS
  100.  MOV WORD PTR BUFSG,ES  ;STORE BUFFER SEGMENT
  101.  
  102.  CMP BYTE PTR HDNUM,DL ;IS IT HARD DRIVE?
  103.  JNE NOTHARD
  104.  MOV BP,OFFSET HD    ;SET DISKDATA BLOCK
  105.  MOV AX,OFFSET HKEY
  106.  MOV WORD PTR KEY,AX ;SET KEY
  107.  JMP PROCRQ
  108. NOTHARD:
  109.  MOV AX,OFFSET FKEY
  110.  MOV WORD PTR KEY,AX ;SET FLOPPY KEY
  111.  CMP DL,0            ;IS IT DRIVE A?
  112.  JNE NOTDRIVEA
  113.  MOV BP,OFFSET FDA   ;SET DISKDATA BLOCK
  114.  JMP PROCRQ
  115. NOTDRIVEA: 
  116.  CMP DL,1            ;IS IT DRIVE B?
  117.  JNE NOTDRIVEB
  118.  MOV BP,OFFSET FDB   ;SET DISKDATA BLOCK
  119.  JMP PROCRQ
  120. NOTDRIVEB:
  121.  JMP NOPROC
  122.  
  123. PROCRQ: ;RIGHT DRIVE 
  124.  
  125.  MOV BYTE PTR BADKEY,0 ;CLEAR BAD KEY FLAG
  126.  
  127. ;HERE WE ENCRYPT THE DATA IF IT WAS A WRITE 
  128.  CMP BYTE PTR RQTYPE,3 ;IS IT WRITE?
  129.  JNE NOENCRYPT ;IF NOT, DON'T ENCRYPT
  130.  MOV BYTE PTR ENCRYPT,1 ;SET ENCRYPT MODE
  131.  CALL CRYPTIT ;ENCRYPT THE DATA
  132.  CMP BYTE PTR BADKEY,1
  133.  JE BACKFROMBIOS ;SKIP WRITE IF BAD KEY/NOT LOGGED IN
  134.  
  135. ;HERE WE DO THE ACTUAL DISK OPERATION 
  136. NOENCRYPT: 
  137.  PUSHF
  138.  PUSH CS
  139.  MOV AX,OFFSET BACKFROMBIOS
  140.  PUSH AX ;HERE WE ARE FAKING AN INT
  141.  MOV AH,BYTE PTR RQTYPE
  142.  MOV AL,BYTE PTR NUMSEC
  143.  MOV CX,WORD PTR CALLCX
  144.  MOV DH,BYTE PTR STHD
  145.  MOV DL,BYTE PTR DRIVE
  146.  MOV ES,WORD PTR BUFSG
  147.  MOV BX,WORD PTR BUFOS
  148.  JMP INT_JOUT ;GO TO BIOS
  149. BACKFROMBIOS:
  150.  PUSHF
  151.  PUSH AX
  152.  
  153. ;HERE WE DECRYPT THE DATA
  154.  MOV BYTE PTR ENCRYPT,0 ;SET DECRYPT MODE
  155.  CALL CRYPTIT ;DECRYPT THE DATA
  156.  
  157. ;HERE WE RETURN TO THE CALLING PROGRAM
  158.  POP AX ;INT RETURN CODE
  159.  POP BX ;FLAGS
  160.  
  161.  CMP BYTE PTR BADKEY,1 ;RETURN FAKE ERROR?
  162.  JNE NOERRRET
  163.  OR BL,1      ;SET CARRY IF KEY BAD
  164.  MOV AH,80h   ;SIMULATE NO DISK PRESENT ERROR 
  165.  
  166. NOERRRET:
  167.  MOV ES,WORD PTR STKSEG 
  168.  MOV SI,WORD PTR STKOFS
  169.  MOV ES:[SI+4],BX ;PUT NEW FLAGS WHERE IRET WILL RECALL THEM
  170.  
  171. RETPROG:
  172.  POP ES
  173.  POP DS
  174.  POP BP
  175.  POP DI
  176.  POP SI
  177.  POP DX
  178.  POP CX
  179.  POP BX
  180.  CLI
  181.  MOV SS,WORD PTR CS:STKSEG
  182.  MOV SP,WORD PTR CS:STKOFS ;RESTORE USER STACK
  183.  STI
  184.  IRET ;RETURN TO PROGRAM, LOADING MODIFIED FLAGS
  185.                             
  186. NOPROC: ;REQUESTS NOT PROCESSED JUMP HERE 
  187.  POP ES
  188.  POP DS
  189.  POP BP
  190.  POP DI
  191.  POP SI
  192.  POP DX
  193.  POP CX
  194.  POP BX
  195.  POP AX
  196.  CLI
  197.  MOV SS,WORD PTR CS:STKSEG
  198.  MOV SP,WORD PTR CS:STKOFS ;RESTORE USER STACK
  199.  STI
  200.  
  201. INT_JOUT: 
  202.  DB 0EAh,00,00,00,00 ;JMP FAR
  203.  
  204. CRYPTIT: ;THIS ENCRYPTS OR DECRYPTS THE BUFFER
  205.  MOV AL,BYTE PTR NUMSEC
  206.  MOV BYTE PTR SECLFT,AL ;LOAD SECTOR COUNTER
  207.  MOV AX,WORD PTR STCYL
  208.  MOV WORD PTR CURCYL,AX ;LOAD CURRENT CYLINDER
  209.  MOV AL,BYTE PTR STHD
  210.  MOV BYTE PTR CURHD,AL  ;LOAD CURRENT HEAD
  211.  MOV AL,BYTE PTR STSEC
  212.  MOV BYTE PTR CURSEC,AL ;LOAD CURRENT SECTOR
  213.  MOV AX,WORD PTR BUFOS
  214.  MOV WORD PTR BUFPS,AX  ;LOAD BUFFER POINTER
  215.  
  216. CRYPTLOOP: 
  217.  CMP BYTE PTR SECLFT,0
  218.  JE DONECRYPT ;CHECK FOR LAST SECTOR
  219.  
  220.  MOV AX,WORD PTR CURCYL
  221.  CMP AX,[BP].FIRSTCYL
  222.  JB DONTCRYPTSEC
  223.  JNE NOTBOOTSEC
  224.  
  225.  MOV AL,BYTE PTR CURHD 
  226.  CMP AL,[BP].FIRSTHD
  227.  JB DONTCRYPTSEC
  228.  JNE NOTBOOTSEC
  229.  
  230.  MOV AL,BYTE PTR CURSEC
  231.  CMP AL,[BP].FIRSTSEC
  232. ;DO WE NEED A JB HERE? 
  233.  JNE NOTBOOTSEC
  234.  
  235.  CALL LOADBS ;LOAD DATA FROM BOOT SECTOR
  236.  JMP DONTCRYPTSEC
  237.  
  238. NOTBOOTSEC:
  239.  MOV AX,WORD PTR CURCYL
  240.  CMP AX,[BP].LASTCYL
  241.  JA DONTCRYPTSEC
  242.  
  243.  CMP [BP].ACTIVE,1
  244.  JE DOCRYPTSEC    ;CHECK ACTIVE FLAG
  245.  CMP BYTE PTR DRIVE,1
  246.  JBE DONTCRYPTSEC
  247.  MOV BYTE PTR BADKEY,1
  248.  JMP DONTCRYPTSEC
  249. DOCRYPTSEC:
  250.  CALL CRYPTSEC ;ENCRYPT CURRENT SECTOR
  251. DONTCRYPTSEC: 
  252.  CALL NEXTSEC  ;GO ON TO NEXT SECTOR
  253.  JMP CRYPTLOOP     ;LOOP
  254. DONECRYPT: RET
  255.  
  256. CRYPTSEC: ;HERE WE CRYPT ONE SECTOR
  257. ;SET UP IV 
  258.  MOV AX,WORD PTR CURCYL
  259.  MOV WORD PTR IV,AX
  260.  MOV AL,BYTE PTR CURHD
  261.  MOV BYTE PTR IV+2,AL
  262.  MOV AL,BYTE PTR CURSEC
  263.  MOV BYTE PTR IV+3,AL
  264.  MOV AX,[BP].SERIAL
  265.  MOV WORD PTR IV+4,AX
  266.  MOV AX,[BP].SERIAL+2
  267.  MOV WORD PTR IV+6,AX ;SET UP IV
  268.  
  269. ;PRE-ENCRYPT IV
  270.  MOV AX,1  ;ACTUALLY ZERO BLOCKS, WILL JUST PRE-ENCRYPT IV
  271.  PUSH AX   ;STORE NUMBER OF BLOCKS
  272.  SUB SP,8 ;PRETEND TO PUSH PLAINTEXT/CIPHERTEXT ADDRESSES
  273.  MOV AX,WORD PTR KEY
  274.  PUSH CS
  275.  PUSH AX
  276.  MOV AX,OFFSET IV
  277.  PUSH CS
  278.  PUSH AX
  279.  PUSH AX ;MAKE IT LOOK LIKE A FAR CALL FOR IDEACFB
  280.  CALL _IDEACFB
  281.  ADD SP,20 ;REMOVE EXTRA WORD
  282.  
  283. ;ENCRYPT/DECRYPT THE BLOCK 
  284.  MOV AX,[BP].SECSIZE
  285.  MOV CL,3
  286.  SHR AX,CL ;SECSIZE/8
  287.  INC AX    ;ONE BLOCK (IV) NOT USED
  288.  PUSH AX   ;STORE NUMBER OF BLOCKS
  289.  MOV AX,WORD PTR BUFSG
  290.  MOV BX,WORD PTR BUFPS
  291.  PUSH AX
  292.  PUSH BX
  293.  PUSH AX
  294.  PUSH BX
  295.  MOV AX,WORD PTR KEY
  296.  PUSH CS
  297.  PUSH AX
  298.  MOV AX,OFFSET IV
  299.  PUSH CS
  300.  PUSH AX
  301.  PUSH AX ;MAKE IT LOOK LIKE A FAR CALL FOR IDEACFB
  302.  CMP BYTE PTR ENCRYPT,1
  303.  JNE DECRYPT
  304.  CALL _IDEACFB
  305.  JMP DONE_CRYPTSEC
  306. DECRYPT:
  307.  CALL _IDEACFBX
  308. DONE_CRYPTSEC: 
  309. ; ADD SP,18
  310.  ADD SP,20 ;REMOVE EXTRA WORD
  311.  RET
  312.  
  313. NEXTSEC: ;INCREMENT HEAD, SECTOR, CYLINDER AS NEEDED TO GO TO NEXT SECTOR
  314.  MOV AX,[BP].SECSIZE
  315.  ADD WORD PTR BUFPS,AX ;GO TO NEXT BLOCK IN MEMORY
  316.  DEC BYTE PTR SECLFT   ;COUNT DOWN SECTORS LEFT
  317.  INC BYTE PTR CURSEC   ;INCREMENT SECTOR 
  318.  MOV AL,BYTE PTR CURSEC
  319.  CMP AL,[BP].MAXSEC
  320.  JBE DONE_COUNT
  321.  MOV BYTE PTR CURSEC,1 ;RESET SECTOR
  322.  INC BYTE PTR CURHD    ;INCREMENT HEAD
  323.  MOV AL,BYTE PTR CURHD
  324.  CMP AL,[BP].MAXHD
  325.  JB DONE_COUNT
  326.  MOV BYTE PTR CURHD,0  ;RESET HEAD
  327.  INC WORD PTR CURCYL   ;THEN INCREMENT CYLINDER
  328. DONE_COUNT: RET
  329.  
  330. LOADBS:
  331.  CMP BYTE PTR DRIVE,1
  332.  JA IGNOREBS ;DON'T ALTER PARAMS FOR HARD DRIVE
  333.  MOV [BP].ACTIVE,0 ;DEFAULT OFF
  334.  MOV ES,WORD PTR BUFSG
  335.  MOV SI,WORD PTR BUFPS ;GET ACCESS TO BUFFER
  336.  CMP WORD PTR ES:[SI+510],0AA55h ;CHECK FOR BOOT-RECORD SIGNATURE
  337.  JNE IGNOREBS ;BAILOUT IF BOOT SECTOR LOOKS BAD
  338.  CMP WORD PTR ES:[SI+3],'RC'
  339.  JNE NOTCRYPT
  340.  CMP WORD PTR ES:[SI+5],'PY'
  341.  JNE NOTCRYPT
  342.  MOV AX,WORD PTR FKEYCHK
  343.  CMP WORD PTR ES:[SI+7],AX
  344.  JNE NOTGOODKEY
  345.  MOV AX,WORD PTR FKEYCHK+2
  346.  CMP WORD PTR ES:[SI+9],AX
  347.  JNE NOTGOODKEY
  348.  JMP GOODKEY
  349. NOTGOODKEY: 
  350.  MOV BYTE PTR BADKEY,1
  351.  JMP NOTCRYPT
  352. GOODKEY: 
  353.  MOV [BP].ACTIVE,1 ;TURN ON ENCRYPTION
  354. NOTCRYPT:
  355.  MOV AL,ES:[SI+18h]
  356.  MOV [BP].MAXSEC,AL ;STORE MAX SECTOR
  357.  MOV AL,ES:[SI+1Ah]
  358.  MOV [BP].MAXHD,AL  ;STORE MAX HEAD
  359.  MOV AX,ES:[SI+0Bh]
  360.  MOV [BP].SECSIZE,AX ;STORE BYTES PER SECTOR
  361.  MOV AX,ES:[SI+27h]
  362.  MOV [BP].SERIAL,AX  ;STORE FIRST WORD OF SERIAL NUMBER
  363.  MOV AX,ES:[SI+29h]
  364.  MOV [BP].SERIAL+2,AX ;STORE SECOND WORD OF SERIAL NUMBER
  365. IGNOREBS:
  366.  RET
  367.  
  368. ;VARIABLES HERE WILL BE LOADED BY LOGIN
  369. LOADDATA:
  370. FKEY:   DB 13,10,'Secure Drive Version 1.0',13,10 
  371.         DB 'TSR Installed',13,10,'$'
  372. ALRINS: DB 13,10,'Secure Drive Version 1.0',13,10
  373.         DB 'TSR already resident',13,10,'$'
  374.         DB (104-($-FKEY)) DUP (0aah)      ;FLOPPY ENCRYPTION KEY
  375. FKEYCHK:DW 2 DUP (0ffffh)
  376. HKEY:   DB 104 DUP (0bbh)                 ;HARD DRIVE ENCRYPTION KEY
  377. HDNUM:  DB 0ffh           ;DEVICE NUMBER OF HARD DRIVE TO ENCRYPT
  378. FDA:    DISKDATA <0,0,1,0FFFFh,18,2,512,0>
  379. FDB:    DISKDATA <0,0,1,0FFFFh,18,2,512,0>
  380. HD:     DISKDATA <0FFFFh,0,0,0,0,0,512,0>
  381.  
  382. ;VARIABLES HERE STAY PUT
  383. STKSEG: DW ? ;SEGMENT OF USER STACK
  384. STKOFS: DW ? ;OFFSET OF USER STACK
  385.  
  386. RQTYPE: DB ? ;REQUEST TYPE, AH FROM CALL
  387. DRIVE:  DB ? ;DRIVE FROM CALL
  388. NUMSEC: DB ? ;NUMBER OF SECTORS TO READ (AL FROM CALL)
  389. SECLFT: DB ? ;NUMBER OF SECTORS LEFT TO PROCESS
  390. CALLCX: DW ? ;ORIGINAL CX
  391. KEY:    DW ? ;CURRENTLY SELECTED KEY
  392. BADKEY: DB ? ;KEY BAD FLAG
  393.  
  394. STCYL:  DW ? ;START CYLINDER FROM CALL
  395. CURCYL: DW ? ;CURRENT CYLINDER BEING PROCESSED
  396.  
  397. STSEC:  DB ? ;START SECTOR FROM CALL
  398. CURSEC: DB ? ;CURRENT SECTOR BEING PROCESSED
  399.  
  400. STHD:   DB ? ;START HEAD FROM CALL
  401. CURHD:  DB ? ;CURRENT HEAD BEING PROCESSED
  402.  
  403. BUFOS:  DW ? ;OFFSET OF TARGET BUFFER
  404. BUFPS:  DW ? ;CURRENT POSITION WITHIN BUFFER
  405. BUFSG:  DW ? ;SEGMENT OF TARGET BUFFER
  406.  
  407. ENCRYPT: DB ? ;1 FOR ENCRYPT, 0 FOR DECRYPT
  408. IV:  DB 8 DUP (?)   ;IV FOR CFB
  409.  
  410. ; Copyright (c) 1993 Colin Plumb.  This code may be freely
  411. ; distributed under the terms of the GNU General Public Licence.
  412.  
  413. ; A core operation in IDEA is multiplication modulo 65537.
  414. ; The valid inputs, 1 through 66636 inclusive are represented in
  415. ; 16-bit registers modulo 65536.  I.e. a value of 0 means 65536,
  416. ; or -1.  Thus, we need to test for that specially.  -x, modulo
  417. ; 65537, is 65537-x = 1-x.
  418. ; For any other number, represent the product as a*65536+b.  Since
  419. ; 65536 = -1 (mod 65537), this is the same number as b-a.  Should
  420. ; this result be negautive (generate a borrow), -n mod 65537 = 1-n
  421. ; mod 65536.  Or in other words, if you add the borrow bit back on,
  422. ; you get the right answer.
  423.  
  424. ; This is what the assembly code does.  It forms a zero, and adds
  425. ; that on with carry.
  426.  
  427. ; Another useful optimisation takes advantage of the fact that
  428. ; a and b are equal only if the answer is congruent to 0 mod 65537.
  429. ; Since 65537 is prime, this happens only if one of the inputs is
  430. ; congruent to 0 mod 65537.  Since the inputs are all less than 65537,
  431. ; this means it must have been zero.
  432.  
  433. ; The code below tests for a zero result of the subtraction, and if
  434. ; one arises, it branches out of line to figure out what happened.
  435.  
  436.  
  437. ; This code implemets the IDEA encryption algorithm.
  438. ; It follows in pseudo-C, where the * operator operates
  439. ; modulo 65537, as Idea needs.  (If you don't understand,
  440. ; learn IDEA better.)
  441.  
  442. ; IDEA is works on 16-bit units.  If you're processing bytes,
  443. ; it's defined to be big-endian, so an Intel machine needs to
  444. ; swap the bytes around.
  445.  
  446. ; void Idea(u_int16 *in, u_int16 *out, u_int16 *key)
  447. ; {
  448. ;        register u+int16 x0, x1, x2, x3, s1, s2, round;
  449. ;
  450. ;        x0 = *in++;  x1 = *in++;  x2 = *in++;  x3 = *in;
  451. ;
  452. ;        for (round = 0; round < 8; round++) {
  453. ;                x0 *= *key++;
  454. ;                x1 += *key++;
  455. ;                x2 += *key++;
  456. ;                x3 *= *key++;
  457. ;
  458. ;                s1  = x1;  s2  = x2;
  459. ;                x2 ^= x0;  x1 ^= x3;
  460. ;
  461. ;                x2 *= *key++;
  462. ;                x1 += x2;
  463. ;                x1 *= *key++;
  464. ;                x2 += x1;
  465. ;
  466. ;                x0 ^= x1;  x3 ^= x2;
  467. ;                x1 ^= s2;  x2 ^= s1;
  468. ;        }
  469. ;        *out++ = x0 * *key++;
  470. ;        *out++ = x2 + *key++;        /* Yes, this is x2, not x1 */
  471. ;        *out++ = x1 + *key++;
  472. ;        *out   = x3 * *key;
  473. ; }
  474.  
  475. ; ds:si points to key, ax, dx are temps, args in bx, cx, di, bp
  476. ; Trashes *all* registers.  direction flag must be clear.
  477. ; Leaves es zero.
  478.  
  479. ; Since there is no spare register to hold the loop count, I make
  480. ; clever use of the stack, pushing the start of the loop several
  481. ; times and using a ret instruction to do the return.
  482.  
  483. ; Annoyingly, lods is fastest on 8086's, but other techniques are
  484. ; best on 386's.  Well, that's what the manual says, but real
  485. ; life is different.  USELODS wins on a 386SX, at least.
  486. ; Leave it set for all platforms.
  487.  
  488. USELODS        equ        1
  489.  
  490. ; bp must be x0 for some of the code below to work
  491. x0        equ        bp
  492. x1        equ        bx
  493. x2        equ        cx
  494. x3        equ        di
  495. ; di must be x3 for some of the code below to work
  496.  
  497. ;; Now, this is rather interesting.  We test for zero arguments
  498. ;; after the multiply.  Assuming random inputs, one or both are
  499. ;; zero (2^17-1)/2^32, or approximately 1/32786 of the time.
  500. ;; Encryption in any feedback mode produces essentially random
  501. ;; inputs, so average-case analysis is okay.  While we don't
  502. ;; want the out-of-line code to waste time, it is not worth
  503. ;; slowing down the in-line case to speed it up.
  504. ;;
  505. ;; Basically, we start inverting the source x, and if that was 0,
  506. ;; we use the inverse of the key instead.
  507.  
  508. Core1Z:
  509.         neg        x0
  510.         jnz        Core1Za
  511. if USELODS
  512.         sub        x0,[si-2]
  513. else
  514.         sub        x0,[si]
  515. endif
  516. Core1Za:
  517.         inc        x0
  518.         jmp        Core1done
  519. Core2Z:
  520.         neg        x3
  521.         jnz        Core2Za
  522. if USELODS
  523.         sub        x3,[si-2]
  524. else
  525.         sub        x3,[si+6]
  526. endif
  527. Core2Za:
  528.         inc        x3
  529.         jmp        Core2done
  530. Core3Z:
  531.         neg        x2
  532.         jnz        Core3Za
  533. if USELODS
  534.         sub        x2,[si-2]
  535. else
  536.         sub        x2,[si+8]
  537. endif
  538. Core3Za:
  539.         inc        x2
  540.         jmp        Core3done
  541. Core4Z:
  542.         neg        x1
  543.         jnz        Core4Za
  544. if USELODS
  545.         sub        x1,[si-2]
  546. else
  547.         sub        x1,[si+10]
  548. endif
  549. Core4Za:
  550.         inc        x1
  551.         jmp        Core4done
  552.  
  553. ; We need a constant 0 that we can move into a register without affecting
  554. ; the carry flag (as the classic xor ax,ax is wont to do), so we use the
  555. ; es register for a constant 0 source.  This is okay even in protected
  556. ; mode.  (I *told* you this was tricky code!)
  557.  
  558. ; BTW, since you wanted to know, this is 8 + 78*4 + 16 = 336 instructions.
  559.  
  560. Core        proc        near
  561.         xor        ax,ax
  562.         mov        es,ax
  563.         mov        ax,OFFSET Finish
  564.         push        ax
  565.         mov        ax,OFFSET Coreloop
  566.         push        ax        ; Loop 3 times, then return
  567.         push        ax
  568.         push        ax
  569.  
  570. Coreloop:
  571. if USELODS
  572.         lodsw
  573. else
  574.         mov        ax,[si]                ; x0 *= *key++
  575. endif
  576.         mul        x0
  577.         sub        ax,dx
  578.         jz        Core1Z
  579.         mov        x0,es
  580.         adc        x0,ax
  581. Core1done:
  582.  
  583. if USELODS
  584.         lodsw
  585.         add        x1,ax
  586.         lodsw
  587.         add        x2,ax
  588. else
  589.         add        x1,[si+2]        ; x1 += *key++
  590.         add        x2,[si+4]        ; x2 += *key++
  591. endif
  592.  
  593. if USELODS
  594.         lodsw
  595. else
  596.         mov        ax,[si+6]        ; x3 += *key++
  597. endif
  598.         mul        x3
  599.         sub        ax,dx
  600.         jz        Core2Z
  601.         mov        x3,es
  602.         adc        x3,ax
  603. Core2done:
  604.  
  605.         push        x1                  ; s1 = x1
  606.         push        x2                ; s2 = x2
  607.  
  608.         xor        x1,x3                ; x1 ^= x3
  609.         xor        x2,x0                ; x2 ^= x0
  610.  
  611. if USELODS
  612.         lodsw
  613. else
  614.         mov        ax,[si+8]        ; x2 *= *key++
  615. endif
  616.         mul        x2
  617.         sub        ax,dx
  618.         jz        Core3Z
  619.         mov        x2,es
  620.         adc        x2,ax
  621. Core3done:
  622.  
  623.         add        x1,x2                ; x1 += x2
  624.  
  625. if USELODS
  626.         lodsw
  627. else
  628.         mov        ax,[si+10]        ; x1 *= *key++
  629. endif
  630.         mul        x1
  631.         sub        ax,dx
  632.         jz        Core4Z
  633.         mov        x1,es
  634.         adc        x1,ax
  635. Core4done:
  636.  
  637.         add        x2,x1                ; x2 += x1
  638.  
  639.         xor        x0,x1                ; x0 ^= x1
  640.         xor        x3,x2                ; x3 ^= x2
  641.  
  642.         pop        dx
  643.         xor        x1,dx                ; x1 ^= s2
  644.         pop        dx
  645.         xor        x2,dx                ; x2 ^= s1
  646.  
  647. ; Second unrolling of loop
  648. if USELODS
  649.         lodsw
  650. else
  651.         mov     ax,[si+12]          ; x0 *= *key++
  652. endif
  653.         mul        x0
  654.         sub        ax,dx
  655.         jz        Core5Z
  656.         mov        x0,es
  657.         adc        x0,ax
  658. Core5done:
  659.  
  660. if USELODS
  661.         lodsw
  662.         add        x1,ax
  663.         lodsw
  664.         add        x2,ax
  665. else
  666.         add        x1,[si+14]        ; x1 += *key++
  667.         add        x2,[si+16]        ; x2 += *key++
  668. endif
  669.  
  670. if USELODS
  671.         lodsw
  672. else
  673.         mov        ax,[si+18]        ; x3 *= *key++
  674. endif
  675.         mul        x3
  676.         sub        ax,dx
  677.         jz        Core6Z
  678.         mov        x3,es
  679.         adc        x3,ax
  680. Core6done:
  681.  
  682.         push        x1                   ; s1 = x1
  683.         push        x2                ; s2 = x2
  684.  
  685.         xor        x1,x3                ; x1 ^= x3
  686.         xor        x2,x0                ; x2 ^= x0
  687.  
  688. if USELODS
  689.         lodsw
  690. else
  691.         mov        ax,[si+20]        ; x2 *= *key++
  692. endif
  693.         mul        x2
  694.         sub        ax,dx
  695.         jz        Core7Z
  696.         mov        x2,es
  697.         adc        x2,ax
  698. Core7done:
  699.  
  700.         add        x1,x2                ; x1 += x2
  701.  
  702. if USELODS
  703.         lodsw
  704. else
  705.         mov        ax,[si+22]        ; x1 *= *key++
  706. endif
  707.         mul        x1
  708.         sub        ax,dx
  709.         jz        Core8Z
  710.         mov        x1,es
  711.         adc        x1,ax
  712. Core8done:
  713.  
  714.         add        x2,x1                ; x2 += x1
  715.  
  716.         xor        x0,x1                ; x0 ^= x1
  717.         xor        x3,x2                ; x3 ^= x2
  718.  
  719.         pop        dx
  720.         xor        x1,dx                ; x1 ^= s2
  721.         pop        dx
  722.         xor        x2,dx                ; x2 ^= s1
  723.  
  724. ife USELODS
  725.         lea        si,[si+24]
  726. endif
  727.  
  728.         ret        ; Used as a loop instruction!
  729.  
  730. Core5Z:
  731.         neg        x0
  732.         jnz        Core5Za
  733. if USELODS
  734.         sub        x0,[si-2]
  735. else
  736.         sub        x0,[si+12]
  737. endif
  738. Core5Za:
  739.         inc        x0
  740.         jmp        Core5done
  741. Core6Z:
  742.         neg        x3
  743.         jnz        Core6Za
  744. if USELODS
  745.         sub        x3,[si-2]
  746. else
  747.         sub        x3,[si+18]
  748. endif
  749. Core6Za:
  750.         inc        x3
  751.         jmp        Core6done
  752. Core7Z:
  753.         neg        x2
  754.         jnz        Core7Za
  755. if USELODS
  756.         sub        x2,[si-2]
  757. else
  758.         sub        x2,[si+20]
  759. endif
  760. Core7Za:
  761.         inc        x2
  762.         jmp        Core7done
  763. Core8Z:
  764.         neg        x1
  765.         jnz        Core8Za
  766. if USELODS
  767.         sub        x1,[si-2]
  768. else
  769.         sub        x1,[si+22]
  770. endif
  771. Core8Za:
  772.         inc        x1
  773.         jmp        Core8done
  774. Core9Z:
  775.         neg        x0
  776.         jnz        Core9Za
  777. if USELODS
  778.         sub        x0,[si-2]
  779. else
  780.         sub        x0,[si]
  781. endif
  782. Core9Za:
  783.         inc        x0
  784.         jmp        Core9done
  785. ; Special: compute into dx (zero on entry)
  786. Core10Z:
  787.         sub        dx,x3
  788.         jnz        Core10Za
  789. if USELODS
  790.         sub        dx,[si-2]
  791. else
  792.         sub        dx,[si+6]
  793. endif
  794. Core10Za:
  795.         inc        dx
  796. ;        jmp        Core10done
  797.         ret
  798.  
  799.  
  800. Finish:
  801. if USELODS
  802.         lodsw
  803. else
  804.         mov        ax,[si]                ; x0 *= *key++
  805. endif
  806.         mul        x0
  807.         sub        ax,dx
  808.         jz        Core9Z
  809.         mov        x0,es
  810.         adc        x0,ax
  811. Core9done:
  812.  
  813.         xchg        x1,x2
  814. if USELODS
  815.         lodsw
  816.         add        x1,ax
  817.         lodsw
  818.         add        x2,ax
  819. else
  820.         add        x1,[si+2]        ; x1 += *key++
  821.         add        x2,[si+4]       ; x2 += *key++
  822. endif
  823.  
  824. ; This is special: compute into dx, not x3
  825. if USELODS
  826.         lodsw
  827. else
  828.         mov        ax,[si+6]        ; x3 *= *key++
  829. endif
  830.         mul        x3
  831.         sub        ax,dx
  832.         mov        dx,es
  833.         jz        Core10Z
  834.         adc        dx,ax
  835. Core10done:
  836.  
  837.         ret
  838.  
  839.         endp
  840.  
  841. ; Okay, the basic plan for the CFB kernel is
  842. ; get x0,x1,x2,x3
  843. ; get key pointer
  844. ; call core
  845. ; get buffer pointers
  846. ;Loop:
  847. ; lodsw
  848. ; xor        ax,x0
  849. ; mov   x0,ax
  850. ; stosw
  851. ; lodsw
  852. ; xor        ax,x1
  853. ; mov        x0,ax
  854. ; stosw
  855. ; lodsw
  856. ; xor        ax,x2
  857. ; mov        x0,ax
  858. ; stosw
  859. ; lodsw
  860. ; xor        ax,x3
  861. ; mov        x3,ax
  862. ; stosw
  863. ; push buffer pointers
  864. ; get key pointer
  865. ; call        core
  866. ; pop buffer pointers
  867. ; loop
  868. ; lodsw/xor/etc.
  869. ;
  870. ;
  871. ; This function is designed to go in the middle of a byte-granularity
  872. ; CFB engine.  It performs "len" encryptions of the IV, encrypting
  873. ; 8*(len-1) bytes from the source to the destination.  The idea is
  874. ; that you first xor any odd leading bytes, then call this function,
  875. ; then xor up to 8 trailing bytes.
  876.  
  877. ; The main loop in this is 38 instructions, plus the 336 for the core
  878. ; makes 374 total.  That's 46.75 instructions per byte.
  879. ; (It's the same for IdeaCFBx)
  880.  
  881. ; IV, key, plain, cipher, len
  882. ;        public        _IdeaCFB
  883. ;_IdeaCFB proc far       ; Args are at [sp+4]
  884. _IDEACFB:        
  885.         cld
  886.         push        bp
  887.         push        si
  888.         push        di
  889.         push        ds        ; 8 more words here, so args are at [sp+12]
  890. ; To be precise, IV is at 12, key at 16, plain at 20,
  891. ; cipher at 24 and len at 28
  892.         mov        bp,sp
  893.         lds        si,[bp+12]        ; IV
  894. ; Load and byte-swap IV
  895.         mov        ax,[si]
  896.         xchg        ah,al
  897.         mov        x1,[si+2]
  898.         mov        x2,[si+4]
  899.         xchg        bh,bl
  900.         xchg        ch,cl
  901.         mov        dx,[si+6]
  902.         xchg        dh,dl
  903.  
  904.         lds        si,[bp+16]        ; Key
  905.         mov        x0,ax
  906.         mov        x3,dx
  907.  
  908.         call        Core
  909. IdeaCFBLoop:
  910. ;        mov        ax,x0
  911. ;        mov        bp,sp
  912. ;        dec        WORD PTR [bp+28]        ; Decrement count
  913. ;        jz        IdeaCFBEnd
  914. ;        lds        si,[bp+20]
  915. ;        les        di,[bp+24]
  916. ;        mov        x0,ax
  917. ; Alternate code: (which is faster?  Two moves or three segment overrides?)
  918.         mov        si,sp
  919.         dec        WORD PTR ss:[si+28]
  920.         jz        IdeaCFBEnd
  921.         les        di,ss:[si+24]
  922.         lds        si,ss:[si+20]
  923.  
  924.         lodsw
  925.         xchg        ah,al
  926.         xor        ax,x0
  927.         mov        x0,ax
  928.         xchg        ah,al
  929.         stosw
  930.         lodsw
  931.         xchg        ah,al
  932.         xor        ax,x1
  933.         mov        x1,ax
  934.         xchg        ah,al
  935.         stosw
  936.         lodsw
  937.         xchg        ah,al
  938.         xor        ax,x2
  939.         mov        x2,ax
  940.         xchg        ah,al
  941.         stosw
  942.         lodsw
  943.         xchg        ah,al
  944.         xor        ax,dx
  945.         mov        dx,ax
  946.         xchg        ah,al
  947.         stosw
  948.  
  949. ;        mov        ax,x0
  950. ;        mov        bp,sp
  951. ;        mov        [bp+20],si        ; Save source offset
  952. ;        mov        [bp+24],di        ; Save destination offset
  953. ;        lds        si,[bp+16]        ; Key
  954. ;        mov        x0,ax                ; Get x0 in place for another iteration
  955. ; Alternate code for the above: (which is faster?  One move or three ss:?)
  956.         mov        ax,si
  957.         mov        si,sp
  958.         mov        ss:[si+20],ax
  959.         mov        ss:[si+24],di
  960.         lds        si,ss:[si+16]
  961.  
  962.         mov        x3,dx                ; Get x3 in place
  963.         mov        ax,OFFSET IdeaCFBLoop
  964.         push        ax
  965.         jmp        Core
  966.  
  967. IdeaCFBEnd:
  968. ;        lds        si,[bp+12]
  969.         lds        di,ss:[si+12]        ; Get IV for writing back
  970.  
  971.         mov        ax,x0
  972.         xchg        ah,al
  973.         mov        [di],ax                ; Use stosw?
  974.         xchg        bh,bl
  975.         xchg        ch,cl
  976.         mov        [di+2],x1
  977.         mov        [di+4],x2
  978.         xchg        dh,dl
  979.         mov        [di+6],dx
  980.  
  981.         pop        ds
  982.         pop        di
  983.         pop        si
  984.         pop        bp
  985.  
  986.         ret
  987.  
  988.         endp
  989.  
  990. ; This decoding step is similar, except that instead of
  991. ;        lods
  992. ;        xor        x0,ax
  993. ;        mov        ax,x0
  994. ;         stos
  995. ; the feedback step is
  996. ;        lods
  997. ;        xchg        x0,ax
  998. ;        xor        ax,x0
  999. ;        stos
  1000.  
  1001. ; IV, key, cipher, plain, len
  1002. ;        public        _IdeaCFBx
  1003. ;_IdeaCFBx proc far       ; Args are at [sp+4]
  1004. _IDEACFBX:        
  1005.         cld
  1006.         push        bp
  1007.         push        si
  1008.         push        di
  1009.         push        ds        ; 8 more words here, so args are at [sp+12]
  1010.         mov        bp,sp
  1011.         lds        si,[bp+12]        ; IV
  1012. ; Load and byte-swap IV
  1013.         mov        ax,[si]
  1014.         xchg        ah,al
  1015.         mov        x1,[si+2]
  1016.         mov        x2,[si+4]
  1017.         xchg        bh,bl
  1018.         xchg        ch,cl
  1019.         mov        dx,[si+6]
  1020.         xchg        dh,dl
  1021.  
  1022.         lds        si,[bp+16]        ; Key
  1023.         mov        x0,ax
  1024.         mov        x3,dx
  1025.  
  1026.         call        Core
  1027. IdeaCFBxLoop:
  1028. ;        mov        ax,x0
  1029. ;        mov        bp,sp
  1030. ;        dec        WORD PTR [bp+28]        ; Decrement count
  1031. ;        jz        IdeaCFBxEnd
  1032. ;        lds        si,[bp+20]
  1033. ;        les        di,[bp+24]
  1034. ;        mov        x0,ax
  1035. ; Alternate code: (which is faster?  Two moves or three segment overrides)
  1036.         mov        si,sp
  1037.         dec        WORD PTR ss:[si+28]
  1038.         jz        IdeaCFBxEnd
  1039.         les        di,ss:[si+24]
  1040.         lds        si,ss:[si+20]
  1041.  
  1042.         lodsw
  1043.         xchg        ah,al
  1044.         xchg        x0,ax
  1045.         xor        ax,x0
  1046.         xchg        ah,al
  1047.         stosw
  1048.         lodsw
  1049.         xchg        ah,al
  1050.         xchg        x1,ax
  1051.         xor        ax,x1
  1052.         xchg        ah,al
  1053.         stosw
  1054.         lodsw
  1055.         xchg        ah,al
  1056.         xchg        x2,ax
  1057.         xor        ax,x2
  1058.         xchg        ah,al
  1059.         stosw
  1060.         lodsw
  1061.         xchg        ah,al
  1062.         xchg        dx,ax
  1063.         xor        ax,dx
  1064.         xchg        ah,al
  1065.         stosw
  1066.  
  1067. ;        mov        ax,x0
  1068. ;        mov        bp,sp
  1069. ;        mov        [bp+20],si        ; Save source offset
  1070. ;        mov        [bp+24],di        ; Save destination offset
  1071. ;        lds        si,[bp+16]        ; Key
  1072. ;        mov        x0,ax                ; Get x0 in place for another iteration
  1073. ; Alternate code for the above: (which is faster?  One move or three ss:?)
  1074.         mov        ax,si
  1075.         mov        si,sp
  1076.         mov        ss:[si+20],ax
  1077.         mov        ss:[si+24],di
  1078.         lds        si,ss:[si+16]
  1079.  
  1080.         mov        x3,dx                ; Get x3 in place
  1081.         mov        ax,OFFSET IdeaCFBxLoop
  1082.         push        ax
  1083.         jmp        Core
  1084.  
  1085. IdeaCFBxEnd:
  1086. ;        lds        si:[bp+12]
  1087.         lds        di,ss:[si+12]        ; Get IV for writing back
  1088.  
  1089.         mov        ax,x0
  1090.         xchg        ah,al
  1091.         mov        [di],ax                ; Use stosw?
  1092.         xchg        bh,bl
  1093.         xchg        ch,cl
  1094.         mov        [di+2],x1
  1095.         mov        [di+4],x2
  1096.         xchg        dh,dl
  1097.         mov        [di+6],dx
  1098.  
  1099.  
  1100.         pop        ds
  1101.         pop        di
  1102.         pop        si
  1103.         pop        bp
  1104.  
  1105.         ret
  1106.  
  1107.         endp
  1108. END_OF_FILE:
  1109. END START
  1110.